import 'dart:async';
import 'dart:convert';
import 'package:chathouse/util/font_utils.dart';
import 'package:crypto/crypto.dart';
import 'package:encrypt/encrypt.dart' as encrypt;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'dart:ui';

///监听观察者
final RouteObserver<Route> routeObserver = RouteObserver();

TextButton getTextButton({
  required Widget child,
  required Function onPressed,
  ButtonStyle? style,
  int interval = 500,
}) {
  var time = 0;
  fun() {
    if (DateTime.now().millisecondsSinceEpoch - time < interval) return;
    time = DateTime.now().millisecondsSinceEpoch;
    onPressed();
  }

  return TextButton(
    child: child,
    onPressed: fun,
    style: style,
  );
}

///默認字體樣式
TextStyle getTextStyle(
  double fontSize, {
  Color? color,
  double? height,
  TextDecoration? decoration,
  double? letterSpacing,
  FontType? fontType,
  TextDecorationStyle? decorationStyle,
}) {
  return TextStyle(
      fontSize: fontSize,
      fontFamily: 'GenSen',
      color: color,
      decorationStyle: decorationStyle,
      fontWeight: FontUtils.getTypeStr(fontType ?? FontType.LIGHT),
      decoration: decoration ?? TextDecoration.none,
      letterSpacing: letterSpacing,
      height: height);
}

class BaseUtils {
  static T? getController<T extends GetxController>() {
    if (Get.isRegistered<T>()) {
      return Get.find<T>();
    } else {
      return null;
    }
  }

  /// md5 加密
  static String md5Encoder(String data) {
    var content = const Utf8Encoder().convert(data);
    var digest = md5.convert(content);
    return digest.toString();
  }

  /// aes 加密
  static String aesEncoder(String value, String key) {
    var utfKey = encrypt.Key.fromUtf8(key);
    var iv = encrypt.IV.fromLength(16);
    var encrypter =
        encrypt.Encrypter(encrypt.AES(utfKey, mode: encrypt.AESMode.ecb));
    var encrypted = encrypter.encrypt(value, iv: iv);
    // var decrypted = encrypter.decrypt(encrypted, iv: iv);
    // print("decrypted:" + decrypted);
    // print("encrypted-base64:" + encrypted.base64);
    return encrypted.base64;
  }

  ///设置底部安全距离颜色  默认为背景设色
  static setAppStatusColor({Color? color}) {
    SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
        statusBarIconBrightness: Brightness.dark,
        statusBarBrightness: Brightness.dark,
        statusBarColor: color ?? Colors.transparent));
  }

  ///设置底部安全距离颜色  默认为背景设色
  static setAppBottomColor({Color? color}) {
    SystemChrome.setSystemUIOverlayStyle(
        SystemUiOverlayStyle(systemNavigationBarColor: color ?? Colors.white));
  }

  static showToast(String str) {
    SmartDialog.showToast(str);
  }

  static offAndTo(String offName, String toName, {dynamic arguments}) {
    if (Get.currentRoute == offName) {
      Get.toNamed(toName, arguments: arguments);
      return;
    }
    Get.back();
    offAndTo(offName, toName, arguments: arguments);
  }

  static backTo(String offName) {
    if (Get.currentRoute != offName) {
      Get.back();
      backTo(offName);
    }
  }

  static copyText(String text, {String tips = '複製成功'}) {
    Clipboard.setData(ClipboardData(text: text));
    BaseUtils.showToast(tips);
  }

  //21-5  统一阴影边框
  static List<BoxShadow> getBoxShadow() {
    return [
      BoxShadow(
          color: Colors.black.setAlpha(0.1),
          // color: Colors.blue,
          offset: Offset(-1.w, 4.w), //阴影xy轴偏移量
          blurRadius: 10.w, //阴影模糊程度
          spreadRadius: 1.w //阴影扩散程度
          )
    ];
  }
}

extension IntExt on int {
  int getLine(int lineSum) {
    return (this % lineSum == 0 ? this ~/ lineSum : (this ~/ lineSum) + 1);
  }
}

extension IntNullExt on int? {
  bool get isNullOrZero => this == null || this == 0;

  String get nullStr => this == null ? "0" : this.toString();

  String coinStr(int ratio) {
    num coin = this! / ratio;
    return coin.format;
  }
}

enum MathType { ADD, MINUS, MULTI }

extension NumNullExt on num? {
  String get nullStr => this == null ? "0" : this.toString();

  String get format => this == null
      ? "0"
      : this! % 1 == 0
          ? this!.toInt().toString()
          : this!.toDouble().toString();

  ///num相减精确计算
  num mathFormat(num numB, MathType type) {
    var a = (this! * 100).ceil();
    var b = (numB * 100).ceil();
    int sum;
    num numC;
    switch (type) {
      case MathType.ADD:
        sum = a + b;
        numC = sum / 100;
        break;
      case MathType.MINUS:
        sum = a - b;
        numC = sum / 100;
        break;
      case MathType.MULTI:
        sum = a * b;
        numC = sum / 10000;
        break;
    }
    return numC;
  }
}

extension StringExt on String {
  bool get isExtEmpty => this == "";

  String get removeLast => this.isNullOrEmpty
      ? ''
      : this.replaceRange(this.length - 1, this.length, '');
}

extension StringNullExt on String? {
  String get nullStr => this ?? "";

  bool get isNullOrEmpty => this == null || this == "";
}

extension ListExt on List {
  bool get isExtEmpty => this.length == 0;
}

extension ListNullExt on List? {
  List get nullGet => this ?? [];
}

extension IterableNullExt on Iterable? {
  bool get isNullOrEmpty => this == null || this!.length == 0;
}

extension MapNullExt on Map? {
  bool get isNullOrEmpty => this == null || this!.length == 0;
}

extension WidgetExt on Widget {
  Widget setAutoFocus(List<FocusNode> focusList) {
    return this.setContainer(color: Colors.transparent).setOnClickListener(
        () => focusList.forEach((element) => element.unfocus()));
  }

  Widget setScroll() {
    return SingleChildScrollView(child: this);
  }

  Widget setVisibility(bool visible) {
    return Visibility(child: this, visible: visible);
  }

  Widget setRefreshIndicator(Future<void> Function() onRefresh) {
    return RefreshIndicator(child: this, onRefresh: onRefresh);
  }

  Widget setWillPopScope(WillPopCallback onWillPop) {
    return WillPopScope(child: this, onWillPop: onWillPop);
  }

  Widget setOnClickListener(GestureTapCallback onTap,
      {bool isInkWell = false,
      int interval = 500,
      GestureLongPressCallback? onLong}) {
    var time = 0;
    fun() {
      if (DateTime.now().millisecondsSinceEpoch - time < interval) return;
      time = DateTime.now().millisecondsSinceEpoch;
      onTap();
    }

    return isInkWell
        ? InkWell(onTap: fun, child: this, onLongPress: onLong)
        : GestureDetector(child: this, onTap: fun, onLongPress: onLong);
  }

  Widget setCenter({bool isSet = true}) {
    return isSet ? Center(child: this) : this;
  }

  Widget setOnLongClickListener(GestureLongPressCallback onLongPress) {
    return GestureDetector(child: this, onLongPress: onLongPress);
  }

  Widget setOnFutureClickListener(Function onFutureClick) {
    return GestureDetector(child: this, onTap: () => onFutureClick());
  }

  Widget setAlpha(double alpha) {
    return Opacity(child: this, opacity: alpha);
  }

  Widget setContainer(
      {double? width,
      double? height,
      double? mainAxisSize,
      EdgeInsets? margin,
      AlignmentGeometry? alignment,
      Color? color,
      EdgeInsets? padding,
      BoxConstraints? constraints,
      Decoration? foregroundDecoration,
      Decoration? decoration,
      Key? key}) {
    return Container(
      alignment: alignment,
      constraints: constraints,
      key: key,
      decoration: decoration,
      foregroundDecoration: foregroundDecoration,
      padding: padding,
      color: color,
      margin: margin,
      width: width,
      height: height,
      child: this,
    );
  }
}

extension ColorExt on Color {
  Color setAlpha(double alpha) {
    return Color.fromARGB((alpha * 255).toInt(), red, green, blue);
  }
}

extension MapExt<K, V> on Map<K, V> {
  V noNullGet<L>(K key) {
    if (containsKey(key)) return this[key] as V;
    if (judgeT<V, List>()) return <L>[] as V;
    if (V is String) return '' as V;
    if (V is int) return 0 as V;
    return '' as V;
  }
}

///判断泛型类型
bool judgeT<T, K>() {
  return <T>[] is List<K>;
}

double hc_ScreenWidth() {
  return window.physicalSize.width/window.devicePixelRatio;
}

double hc_ScreenHeight(){
  return window.physicalSize.height/window.devicePixelRatio;
}

double hc_FitWidth(double width) {
  return hc_ScreenWidth()/375.0 *width;
}

double hc_FitHeight(double height) {
  return hc_ScreenHeight()/667.0 *height;
}